<script setup lang="ts">
import { h, ref, reactive, onMounted } from 'vue'
import { NModal, NCard, NForm, NSpace, NDatePicker, NFormItem, NFormItemGi, NInput, NGrid, NButton, NDataTable, NPagination, NTag, useNotification, useDialog } from 'naive-ui'
import type { FormInst, DataTableRowKey, DataTableColumns } from 'naive-ui'
import http from '@/tools/http'
import { useUserStore } from '@/stores/userStore'
import { useDictStore } from '@/stores/dictStore'

const userStore = useUserStore()
const dictStore = useDictStore()
const notification = useNotification()
const dialog = useDialog()

type RowData = {
    logId?: string
    userId?: string
    apiUrl?: string
    completeDuration?: string
    requestMethod?: string
    contentType?: string
    request?: string
    response?: string
    ip?: string
    address?: string
    browserInfo?: string
    operatingSystemInfo?: string
    operateStatus?: string
    operateTime?: string
}

type SearchFromType = {
    pageNum: number,
    pageSize: number,
    userId?: string,
    apiUrl?: string
    operateTimeRange: [string, string] | null
}

const operateLogTableColumns: DataTableColumns = [
    {
        type: 'selection',
        width: 25
    }, {
        title: "用户ID(账号)",
        key: "userId",
        width: 70
    }, {
        title: "接口URL",
        key: "apiUrl",
        width: 120
    }, {
        title: "耗时",
        key: "completeDuration",
        width: 30,
        render(rowData: RowData, rowIndex: number) {
            return rowData.completeDuration + ' ms'
        }

    }, {
        title: "操作状态",
        key: "operateStatus",
        width: 50,
        render(rowData: RowData, rowIndex: number) {
            return h(
                NTag,
                {
                    type: rowData.operateStatus === '0' ? 'success' : 'error'
                },
                () => dictStore.dictItem("OPERATE_STATUS", rowData.operateStatus)
            )
        }
    }, {
        title: "操作日期",
        key: "operateTime",
        width: 100
    }, {
        title: "操作",
        key: "actions",
        width: 72,
        fixed: 'right',
        render(rowData: RowData, rowIndex: number) {
            return userStore.hasAuth("operate-log") ? h(
                NSpace, null,
                () => [
                    h(
                        NButton,
                        {
                            size: "small",
                            onclick: () => openOperateLogDetail(rowData)
                        },
                        { default: () => "查看详情" }
                    )
                ]
            ) : null
        }
    }
]

const operateLogData = reactive<any>({
    list: [],
    pageNum: 1,
    pageSize: 10,
    pages: 1,
    total: 0
})

const operateLogSearchFormValue = reactive<SearchFromType>({
    pageNum: 1,
    pageSize: 10,
    userId: "",
    apiUrl: "",
    operateTimeRange: null
})

const visiable = ref<boolean>(false)
const formRef = ref<FormInst | null>(null)
const formData = reactive<RowData>({
    logId: "",
    userId: "",
    apiUrl: "",
    completeDuration: "",
    requestMethod: "",
    contentType: "",
    request: "",
    response: "",
    ip: "",
    address: "",
    browserInfo: "",
    operatingSystemInfo: "",
    operateStatus: "",
    operateTime: ""
})

const checkedRowKeys = ref<DataTableRowKey[]>([])

onMounted(() => {
    pageOperateLog()
})

function handleCheckRowKeys(rowKeys: DataTableRowKey[]) {
    checkedRowKeys.value = rowKeys
}

function pageNumChange(pageNum: number) {
    operateLogSearchFormValue.pageNum = pageNum
    pageOperateLog()
}

function pageSizeChange(pageSize: number) {
    operateLogSearchFormValue.pageSize = pageSize
    pageOperateLog()
}

function openOperateLogDetail(row: RowData) {
    const request = {
        logId: row.logId
    }
    http.post("/system/log/operate", request).then(({ data }) => {
        if (data.code === "0") {
            visiable.value = true
            formData.logId = data.data.logId
            formData.userId = data.data.userId
            formData.apiUrl = data.data.apiUrl
            formData.completeDuration = data.data.completeDuration
            formData.requestMethod = data.data.requestMethod
            formData.contentType = data.data.contentType
            formData.request = data.data.request
            formData.response = data.data.response
            formData.ip = data.data.ip
            formData.address = data.data.address
            formData.browserInfo = data.data.browserInfo
            formData.operatingSystemInfo = data.data.operatingSystemInfo
            formData.operateStatus = data.data.operateStatus
            formData.operateTime = data.data.operateTime
        }
    })
}

function pageOperateLog() {
    let start = ""
    let end = ""
    if (operateLogSearchFormValue.operateTimeRange) {
        start = operateLogSearchFormValue.operateTimeRange[0]
        end = operateLogSearchFormValue.operateTimeRange[1]
    }
    const request = {
        pageNum: operateLogSearchFormValue.pageNum,
        pageSize: operateLogSearchFormValue.pageSize,
        userId: operateLogSearchFormValue.userId,
        apiUrl: operateLogSearchFormValue.apiUrl,
        operateTimeStart: start,
        operateTimeEnd: end
    }
    http.post("/system/log/operate/page", request).then(({ data }) => {
        if (data.code === "0") {
            operateLogData.pageNum = data.data.pageNum
            operateLogData.pageSize = data.data.pageSize
            operateLogData.pages = data.data.pages
            operateLogData.total = data.data.total
            operateLogData.list.length = 0
            for (let i = 0; i < data.data.list.length; i++) {
                operateLogData.list.push(data.data.list[i])
            }
        }
    })
}

function batchDeleteLog() {
    dialog.create({
        title: '温馨提示',
        content: '确定删除选中的日志吗？',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: () => {
            http.post("/system/log/operate/batch-delete", checkedRowKeys.value).then(({ data }) => {
                if (data.code === "0") {
                    notification['success']({
                        content: '删除成功',
                        meta: `${data.msg}`,
                        duration: 2500,
                        keepAliveOnHover: true
                    })
                    pageOperateLog()
                }
            })
        }
    })
}

function clearLog() {
    dialog.create({
        title: '温馨提示',
        content: '确定清空所有日志吗？',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: () => {
            http.post("/system/log/operate/clear").then(({ data }) => {
                if (data.code === "0") {
                    notification['success']({
                        content: '清空成功',
                        meta: `${data.msg}`,
                        duration: 2500,
                        keepAliveOnHover: true
                    })
                    pageOperateLog()
                }
            })
        }
    })
}
</script>

<template>
    <div id="flame-container">
        <div class="search">
            <n-form :model="operateLogSearchFormValue" inline label-placement="left">
                <n-form-item label="用户ID(账号)">
                    <n-input v-model:value="operateLogSearchFormValue.userId" placeholder="请输入用户ID(账号)" clearable />
                </n-form-item>
                <n-form-item label="接口URL">
                    <n-input v-model:value="operateLogSearchFormValue.apiUrl" placeholder="请输入接口URL" clearable />
                </n-form-item>
                <n-form-item label="操作日期">
                    <n-date-picker v-model:formatted-value="operateLogSearchFormValue.operateTimeRange" type="daterange"
                        placeholder="请选择日期范围" clearable />
                </n-form-item>
                <n-form-item>
                    <n-button attr-type="button" @click="pageOperateLog()">查询</n-button>
                </n-form-item>
            </n-form>
        </div>
        <div class="btn-group">
            <n-space>
                <n-button v-if="userStore.hasAuth('operate-log:batch-delete')" :disabled="checkedRowKeys.length === 0"
                    attr-type="button" @click="batchDeleteLog()">批量删除</n-button>
                <n-button v-if="userStore.hasAuth('operate-log:clear')" attr-type="button"
                    @click="clearLog()">清空所有日志</n-button>
            </n-space>
        </div>
        <div class="data-table">
            <n-data-table :scroll-x="742" :scrollbar-props="{ trigger: 'none' }" style="height:100%" flex-height
                :row-key="row => row.logId" @update:checked-row-keys="handleCheckRowKeys" :columns="operateLogTableColumns"
                :data="operateLogData.list" :bordered="false" />
        </div>
        <div class="pagination">
            <n-pagination style="float:right" v-model:page="operateLogData.pageNum" :page-size="operateLogData.pageSize"
                :item-count="operateLogData.total" :page-sizes="[5, 10, 30, 50, 100]" :on-update-page="pageNumChange"
                :on-update-page-size="pageSizeChange" show-quick-jumper show-size-picker />
        </div>
    </div>
    <n-modal v-model:show="visiable">
        <n-card style="width: 700px">
            <n-form ref="formRef" :model="formData" label-width="100px" label-placement="left"
                require-mark-placement="left">
                <n-grid :cols="2">
                    <n-form-item-gi :span="2" label="用户ID(账号)">
                        {{ formData.userId }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="1" label="接口URL">
                        {{ formData.apiUrl }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="1" label="操作状态" path="operateStatus">
                        <n-tag :type="formData.operateStatus === '0' ? 'success' : 'error'">{{
                            dictStore.dictItem("OPERATE_STATUS",
                                formData.operateStatus) }}</n-tag>
                    </n-form-item-gi>
                    <n-form-item-gi :span="1" label="耗时">
                        {{ formData.completeDuration }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="1" label="IP地址" path="ip">
                        {{ formData.ip }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="1" label="操作地点" path="address">
                        {{ formData.address }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="1" label="浏览器" path="browserInfo">
                        {{ formData.browserInfo }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="1" label="操作系统" path="operatingSystemInfo">
                        {{ formData.operatingSystemInfo }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="1" label="操作日期" path="operateTime">
                        {{ formData.operateTime }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="2" label="请求数据" path="request">
                        {{ formData.request }}
                    </n-form-item-gi>
                    <n-form-item-gi :span="2" label="响应数据" path="response">
                        {{ formData.response }}
                    </n-form-item-gi>
                </n-grid>
            </n-form>
        </n-card>
    </n-modal>
</template>

<style scoped>
.display-flex-end {
    display: flex;
    width: 100%;
    justify-content: flex-end;
}
</style>